// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-11-20

package searched

import (
	"encoding/json"
	"fmt"
	"sort"
	"time"
)

type Item struct {
	Level     string    `json:"level"`
	Message   string    `json:"message"`
	Time      time.Time `json:"time"`
	TimeMs    string    `json:"time_ms"`
	TimeMicro int64     `json:"time_micro"`

	Stack string `json:"stack,omitempty"`

	TraceId            string `json:"trace_id,omitempty"`
	SpanId             string `json:"span_id,omitempty"`
	SpanPosition       int    `json:"span_position,omitempty"`
	ParentSpanId       string `json:"parent_span_id,omitempty"`
	ParentSpanPosition int    `json:"parent_span_position,omitempty"`

	Pid              int      `json:"pid,omitempty"`
	ServiceAddresses []string `json:"service_addresses,omitempty"`
	ServiceHost      string   `json:"service_host,omitempty"`
	ServicePort      int      `json:"service_port,omitempty"`
	ServiceName      string   `json:"service_name,omitempty"`
	ServiceVersion   string   `json:"service_version,omitempty"`

	ItemTotal int     `json:"item_total"`
	SpanCount int     `json:"span_count"`
	SpanList  []*Span `json:"span_list,omitempty"`

	notSortedSpan []*Span
}

// NewItem
// 取出实例.
func NewItem(body []byte) (item *Item, err error) {
	item = &Item{}
	if err = json.Unmarshal(body, item); err == nil {
		item.SpanList = make([]*Span, 0)
		item.notSortedSpan = make([]*Span, 0)
		item.TimeMs = item.Time.Format("15:04:05.999999")
	}
	return
}

func (o *Item) Add(spans []*Span) {
	o.notSortedSpan = append(o.notSortedSpan, spans...)
}

func (o *Item) Sort() {
	var (
		index = make(map[string]*Span)
		key   string
		keys  = make([]string, 0)
	)

	// 1. 构建中间值.
	for i, span := range o.notSortedSpan {
		// 1.1 内部排序.
		span.Sort()

		// 1.2 中间处理.
		key = fmt.Sprintf(`%d-%04d`, span.StartTime, i)
		keys = append(keys, key)
		index[key] = span
	}

	// 2. 中间值排序.
	sort.Strings(keys)

	// 3. 按顺序添加.
	for _, key = range keys {
		if span, ok := index[key]; ok {
			o.SpanList = append(o.SpanList, span)
		}
	}

	// 4. 清理数据.
	o.notSortedSpan = nil
}

func (o *Item) Update() {
	if o.SpanCount = len(o.SpanList); o.SpanCount > 0 {
		for _, span := range o.SpanList {
			span.Update()
			o.ItemTotal += span.ItemTotal
		}
	}
}
